package org.cybzacg.encryption.utils;

import org.cybzacg.encryption.enums.EncryptionAlgorithm;
import org.cybzacg.encryption.enums.EncryptionType;
import org.cybzacg.encryption.model.ValidationResult;

import javax.crypto.SecretKey;
import java.security.Key;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Arrays;
import java.util.Base64;
import java.util.regex.Pattern;

/**
 * 验证工具类
 * 提供加密相关的验证功能
 * 
 * @author encryption team
 * @version 1.0
 */
public class ValidationUtils {
    
    // 密钥长度模式
    private static final Pattern AES_KEY_PATTERN = Pattern.compile("^[A-Za-z0-9+/]{43,44}={0,2}$"); // Base64编码的32字节
    private static final Pattern DES_KEY_PATTERN = Pattern.compile("^[A-Za-z0-9+/]{11}={0,2}$");   // Base64编码的8字节
    private static final Pattern RSA_KEY_PATTERN = Pattern.compile("^[A-Za-z0-9+/]{100,}={0,2}$"); // RSA密钥较长
    
    // 常见算法的最小/最大密钥长度
    private static final int MIN_AES_KEY_SIZE = 128;
    private static final int MAX_AES_KEY_SIZE = 256;
    private static final int DES_KEY_SIZE = 56;
    private static final int TRIPLE_DES_KEY_SIZE = 168;
    private static final int MIN_RSA_KEY_SIZE = 1024;
    private static final int MAX_RSA_KEY_SIZE = 16384;
    
    /**
     * 验证密钥是否有效
     * 
     * @param key 密钥
     * @param algorithm 算法
     * @return 验证结果
     */
    public static ValidationResult validateKey(Key key, EncryptionAlgorithm algorithm) {
        if (key == null) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message("Key cannot be null")
                    .build();
        }
        
        if (algorithm == null) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message("Algorithm cannot be null")
                    .build();
        }
        
        try {
            switch (algorithm) {
                case AES:
                    return validateAESKey(key);
                case DES:
                    return validateDESKey(key);
                case TRIPLE_DES:
                    return validateTripleDESKey(key);
                case RSA:
                    return validateRSAKey(key);
                case BLOWFISH:
                    return validateBlowfishKey(key);
                default:
                    return new ValidationResult.Builder()
                            .valid(false)
                            .message("Unsupported algorithm: " + algorithm)
                            .build();
            }
        } catch (Exception e) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message("Key validation failed: " + e.getMessage())
                    .build();
        }
    }
    
    /**
     * 验证AES密钥
     * 
     * @param key AES密钥
     * @return 验证结果
     */
    public static ValidationResult validateAESKey(Key key) {
        byte[] keyBytes = key.getEncoded();
        if (keyBytes == null) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message("AES key encoding is null")
                    .build();
        }
        
        int keySizeBits = keyBytes.length * 8;
        if (keySizeBits < MIN_AES_KEY_SIZE || keySizeBits > MAX_AES_KEY_SIZE) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message(String.format("AES key size must be between %d and %d bits, got %d", 
                        MIN_AES_KEY_SIZE, MAX_AES_KEY_SIZE, keySizeBits))
                    .build();
        }
        
        if (!isValidAESKeySize(keySizeBits)) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message(String.format("Invalid AES key size: %d bits. Valid sizes are 128, 192, 256", keySizeBits))
                    .build();
        }
        
        return new ValidationResult.Builder()
                .valid(true)
                .message("AES key is valid")
                .build();
    }
    
    /**
     * 验证DES密钥
     * 
     * @param key DES密钥
     * @return 验证结果
     */
    public static ValidationResult validateDESKey(Key key) {
        byte[] keyBytes = key.getEncoded();
        if (keyBytes == null) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message("DES key encoding is null")
                    .build();
        }
        
        int keySizeBits = keyBytes.length * 8;
        if (keySizeBits != DES_KEY_SIZE) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message(String.format("DES key must be exactly %d bits, got %d", DES_KEY_SIZE, keySizeBits))
                    .build();
        }
        
        return new ValidationResult.Builder()
                .valid(true)
                .message("DES key is valid")
                .build();
    }
    
    /**
     * 验证3DES密钥
     * 
     * @param key 3DES密钥
     * @return 验证结果
     */
    public static ValidationResult validateTripleDESKey(Key key) {
        byte[] keyBytes = key.getEncoded();
        if (keyBytes == null) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message("3DES key encoding is null")
                    .build();
        }
        
        int keySizeBits = keyBytes.length * 8;
        if (keySizeBits != TRIPLE_DES_KEY_SIZE) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message(String.format("3DES key must be exactly %d bits, got %d", TRIPLE_DES_KEY_SIZE, keySizeBits))
                    .build();
        }
        
        return new ValidationResult.Builder()
                .valid(true)
                .message("3DES key is valid")
                .build();
    }
    
    /**
     * 验证RSA密钥
     * 
     * @param key RSA密钥
     * @return 验证结果
     */
    public static ValidationResult validateRSAKey(Key key) {
        byte[] keyBytes = key.getEncoded();
        if (keyBytes == null) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message("RSA key encoding is null")
                    .build();
        }
        
        int keySizeBits = keyBytes.length * 8;
        if (keySizeBits < MIN_RSA_KEY_SIZE || keySizeBits > MAX_RSA_KEY_SIZE) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message(String.format("RSA key size must be between %d and %d bits, got %d", 
                        MIN_RSA_KEY_SIZE, MAX_RSA_KEY_SIZE, keySizeBits))
                    .build();
        }
        
        // 检查密钥是否为有效的RSA密钥
        if (!(key instanceof PublicKey) && !(key instanceof PrivateKey)) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message("Key must be a PublicKey or PrivateKey for RSA")
                    .build();
        }
        
        return new ValidationResult.Builder()
                .valid(true)
                .message("RSA key is valid")
                .build();
    }
    
    /**
     * 验证Blowfish密钥
     * 
     * @param key Blowfish密钥
     * @return 验证结果
     */
    public static ValidationResult validateBlowfishKey(Key key) {
        byte[] keyBytes = key.getEncoded();
        if (keyBytes == null) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message("Blowfish key encoding is null")
                    .build();
        }
        
        int keySizeBits = keyBytes.length * 8;
        if (keySizeBits < 32 || keySizeBits > 448 || keySizeBits % 8 != 0) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message(String.format("Blowfish key size must be between 32 and 448 bits and multiple of 8, got %d", keySizeBits))
                    .build();
        }
        
        return new ValidationResult.Builder()
                .valid(true)
                .message("Blowfish key is valid")
                .build();
    }
    
    /**
     * 验证初始化向量(IV)
     * 
     * @param iv 初始化向量
     * @param blockSize 块大小
     * @return 验证结果
     */
    public static ValidationResult validateIV(byte[] iv, int blockSize) {
        if (iv == null) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message("IV cannot be null")
                    .build();
        }
        
        if (iv.length != blockSize) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message(String.format("IV length must be %d bytes, got %d", blockSize, iv.length))
                    .build();
        }
        
        return new ValidationResult.Builder()
                .valid(true)
                .message("IV is valid")
                .build();
    }
    
    /**
     * 验证数据是否为空
     * 
     * @param data 数据
     * @return 验证结果
     */
    public static ValidationResult validateNotEmpty(byte[] data) {
        if (data == null) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message("Data cannot be null")
                    .build();
        }
        
        if (data.length == 0) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message("Data cannot be empty")
                    .build();
        }
        
        return new ValidationResult.Builder()
                .valid(true)
                .message("Data is valid")
                .build();
    }
    
    /**
     * 验证数据长度
     * 
     * @param data 数据
     * @param minLength 最小长度
     * @param maxLength 最大长度
     * @return 验证结果
     */
    public static ValidationResult validateDataLength(byte[] data, int minLength, int maxLength) {
        ValidationResult result = validateNotEmpty(data);
        if (!result.isValid()) {
            return result;
        }
        
        if (data.length < minLength) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message(String.format("Data length must be at least %d bytes, got %d", minLength, data.length))
                    .build();
        }
        
        if (maxLength > 0 && data.length > maxLength) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message(String.format("Data length must not exceed %d bytes, got %d", maxLength, data.length))
                    .build();
        }
        
        return new ValidationResult.Builder()
                .valid(true)
                .message("Data length is valid")
                .build();
    }
    
    /**
     * 验证Base64编码的字符串
     * 
     * @param base64String Base64字符串
     * @return 验证结果
     */
    public static ValidationResult validateBase64(String base64String) {
        if (base64String == null) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message("Base64 string cannot be null")
                    .build();
        }
        
        if (base64String.trim().isEmpty()) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message("Base64 string cannot be empty")
                    .build();
        }
        
        try {
            Base64.getDecoder().decode(base64String);
            return new ValidationResult.Builder()
                    .valid(true)
                    .message("Base64 string is valid")
                    .build();
        } catch (IllegalArgumentException e) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message("Invalid Base64 string: " + e.getMessage())
                    .build();
        }
    }
    
    /**
     * 验证字符串是否符合Base64模式
     * 
     * @param base64String Base64字符串
     * @param pattern 匹配模式
     * @return 验证结果
     */
    public static ValidationResult validateBase64Pattern(String base64String, Pattern pattern) {
        ValidationResult result = validateBase64(base64String);
        if (!result.isValid()) {
            return result;
        }
        
        if (!pattern.matcher(base64String).matches()) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message("String does not match expected Base64 pattern")
                    .build();
        }
        
        return new ValidationResult.Builder()
                .valid(true)
                .message("Base64 pattern is valid")
                .build();
    }
    
    /**
     * 验证算法参数
     * 
     * @param algorithm 算法
     * @param encryptionType 加密类型
     * @return 验证结果
     */
    public static ValidationResult validateAlgorithmParameters(EncryptionAlgorithm algorithm, EncryptionType encryptionType) {
        if (algorithm == null) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message("Algorithm cannot be null")
                    .build();
        }
        
        if (encryptionType == null) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message("Encryption type cannot be null")
                    .build();
        }
        
        // 验证算法和加密类型的匹配
        switch (algorithm) {
            case AES:
            case DES:
            case TRIPLE_DES:
            case BLOWFISH:
                if (encryptionType != EncryptionType.SYMMETRIC) {
                    return new ValidationResult.Builder()
                            .valid(false)
                            .message(String.format("%s must use symmetric encryption type", algorithm))
                            .build();
                }
                break;
            case RSA:
                if (encryptionType != EncryptionType.ASYMMETRIC) {
                    return new ValidationResult.Builder()
                            .valid(false)
                            .message(String.format("%s must use asymmetric encryption type", algorithm))
                            .build();
                }
                break;
            default:
                return new ValidationResult.Builder()
                        .valid(false)
                        .message("Unsupported algorithm: " + algorithm)
                        .build();
        }
        
        return new ValidationResult.Builder()
                .valid(true)
                .message("Algorithm parameters are valid")
                .build();
    }
    
    /**
     * 验证密钥对
     * 
     * @param publicKey 公钥
     * @param privateKey 私钥
     * @param algorithm 算法
     * @return 验证结果
     */
    public static ValidationResult validateKeyPair(PublicKey publicKey, PrivateKey privateKey, EncryptionAlgorithm algorithm) {
        ValidationResult result = validateKey(publicKey, algorithm);
        if (!result.isValid()) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message("Public key validation failed: " + result.getMessage())
                    .build();
        }
        
        result = validateKey(privateKey, algorithm);
        if (!result.isValid()) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message("Private key validation failed: " + result.getMessage())
                    .build();
        }
        
        // 验证密钥对是否匹配（简单的长度检查）
        byte[] pubKeyBytes = publicKey.getEncoded();
        byte[] privKeyBytes = privateKey.getEncoded();
        
        if (pubKeyBytes == null || privKeyBytes == null) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message("Key encoding is null")
                    .build();
        }
        
        return new ValidationResult.Builder()
                .valid(true)
                .message("Key pair is valid")
                .build();
    }
    
    /**
     * 验证盐值
     * 
     * @param salt 盐值
     * @param expectedLength 期望长度
     * @return 验证结果
     */
    public static ValidationResult validateSalt(byte[] salt, int expectedLength) {
        if (salt == null) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message("Salt cannot be null")
                    .build();
        }
        
        if (salt.length != expectedLength) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message(String.format("Salt length must be %d bytes, got %d", expectedLength, salt.length))
                    .build();
        }
        
        return new ValidationResult.Builder()
                .valid(true)
                .message("Salt is valid")
                .build();
    }
    
    /**
     * 验证密码强度
     * 
     * @param password 密码
     * @return 验证结果
     */
    public static ValidationResult validatePasswordStrength(String password) {
        if (password == null) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message("Password cannot be null")
                    .build();
        }
        
        if (password.length() < 8) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message("Password must be at least 8 characters long")
                    .build();
        }
        
        boolean hasUpper = password.chars().anyMatch(Character::isUpperCase);
        boolean hasLower = password.chars().anyMatch(Character::isLowerCase);
        boolean hasDigit = password.chars().anyMatch(Character::isDigit);
        boolean hasSpecial = password.chars().anyMatch(ch -> !Character.isLetterOrDigit(ch));
        
        if (!hasUpper) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message("Password must contain at least one uppercase letter")
                    .build();
        }
        
        if (!hasLower) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message("Password must contain at least one lowercase letter")
                    .build();
        }
        
        if (!hasDigit) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message("Password must contain at least one digit")
                    .build();
        }
        
        if (!hasSpecial) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message("Password must contain at least one special character")
                    .build();
        }
        
        return new ValidationResult.Builder()
                .valid(true)
                .message("Password strength is valid")
                .build();
    }
    
    /**
     * 验证时间戳是否在有效范围内
     * 
     * @param timestamp 时间戳（毫秒）
     * @param maxAge 最大年龄（毫秒）
     * @return 验证结果
     */
    public static ValidationResult validateTimestamp(long timestamp, long maxAge) {
        long currentTime = System.currentTimeMillis();
        long age = Math.abs(currentTime - timestamp);
        
        if (age > maxAge) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message(String.format("Timestamp is too old: %d ms (max allowed: %d ms)", age, maxAge))
                    .build();
        }
        
        return new ValidationResult.Builder()
                .valid(true)
                .message("Timestamp is valid")
                .build();
    }
    
    /**
     * 验证数组是否安全（不包含敏感数据）
     * 
     * @param data 数据数组
     * @return 验证结果
     */
    public static ValidationResult validateSecureArray(byte[] data) {
        if (data == null) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message("Array cannot be null")
                    .build();
        }
        
        // 检查数组是否被清零（安全擦除）
        boolean isZeroed = true;
        for (byte b : data) {
            if (b != 0) {
                isZeroed = false;
                break;
            }
        }
        
        if (isZeroed) {
            return new ValidationResult.Builder()
                    .valid(true)
                    .warning("Array appears to be zeroed (may have been securely erased)")
                    .build();
        }
        
        return new ValidationResult.Builder()
                .valid(true)
                .message("Array is secure")
                .build();
    }
    
    /**
     * 验证算法是否支持
     * 
     * @param algorithm 算法名称
     * @return 验证结果
     */
    public static ValidationResult validateAlgorithmSupport(String algorithm) {
        if (algorithm == null || algorithm.trim().isEmpty()) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message("Algorithm name cannot be null or empty")
                    .build();
        }
        
        try {
            KeyGeneratorUtils.isAlgorithmSupported(algorithm);
            return new ValidationResult.Builder()
                    .valid(true)
                    .message("Algorithm is supported")
                    .build();
        } catch (Exception e) {
            return new ValidationResult.Builder()
                    .valid(false)
                    .message("Algorithm not supported: " + algorithm)
                    .build();
        }
    }
    
    /**
     * 综合验证加密参数
     * 
     * @param data 数据
     * @param key 密钥
     * @param iv 初始化向量
     * @param algorithm 算法
     * @param encryptionType 加密类型
     * @return 验证结果
     */
    public static ValidationResult validateEncryptionParameters(
            byte[] data, Key key, byte[] iv, 
            EncryptionAlgorithm algorithm, EncryptionType encryptionType) {
        
        // 验证数据
        ValidationResult result = validateNotEmpty(data);
        if (!result.isValid()) {
            return result;
        }
        
        // 验证算法参数
        result = validateAlgorithmParameters(algorithm, encryptionType);
        if (!result.isValid()) {
            return result;
        }
        
        // 验证密钥
        result = validateKey(key, algorithm);
        if (!result.isValid()) {
            return result;
        }
        
        // 对于对称加密，验证IV
        if (encryptionType == EncryptionType.SYMMETRIC && iv != null) {
            try {
                int blockSize = EncryptionUtils.getBlockSize(algorithm);
                if (blockSize > 0) {
                    result = validateIV(iv, blockSize);
                    if (!result.isValid()) {
                        return result;
                    }
                }
            } catch (Exception e) {
                return new ValidationResult.Builder()
                        .valid(false)
                        .message("Failed to get block size for IV validation: " + e.getMessage())
                        .build();
            }
        }
        
        return new ValidationResult.Builder()
                .valid(true)
                .message("Encryption parameters are valid")
                .build();
    }
    
    /**
     * 检查AES密钥长度是否有效
     * 
     * @param keySize 密钥长度（位）
     * @return true如果有效
     */
    private static boolean isValidAESKeySize(int keySize) {
        return keySize == 128 || keySize == 192 || keySize == 256;
    }
}
